#include "ukuitaskbtn.h"

#include <QDebug>
#include <QScreen>
#include <QApplication>
#include <QVBoxLayout>
#include <QLayoutItem>
#include <QEvent>
#include <QDragEnterEvent>
#include <QDrag>

#include "ukuiwindow.h"
#include "common/ukuisettings.h"
#include "ukuitaskbar.h"
#include "../panel/customstyle.h"
#include "ukuitaskbarpreviewwidget.h"
#include "iukuipanelplugin.h"

#include "ukuipopup.h"
#include "commonutil.h"


#define PANEL_SETTINGS      "org.ukui.panel.settings"
#define PANEL_SIZE_KEY      "panelsize"
#define ICON_SIZE_KEY       "iconsize"
#define PANEL_POSITION_KEY  "panelposition"


#define PREVIEW_WIDTH		468
#define PREVIEW_HEIGHT		428
#define SPACE_WIDTH			8
#define SPACE_HEIGHT		8
#define THUMBNAIL_WIDTH		(PREVIEW_WIDTH - SPACE_WIDTH)
#define THUMBNAIL_HEIGHT	(PREVIEW_HEIGHT - SPACE_HEIGHT)
#define ICON_WIDTH			48
#define ICON_HEIGHT			48
#define MAX_SIZE_OF_Thumb   16777215

#define SCREEN_MAX_WIDTH_SIZE     1400
#define SCREEN_MAX_HEIGHT_SIZE    1050

#define SCREEN_MIN_WIDTH_SIZE    800
#define SCREEN_MIN_HEIGHT_SIZE   600

#define SCREEN_MID_WIDTH_SIZE    1600

#define PREVIEW_WIDGET_MAX_WIDTH            352
#define PREVIEW_WIDGET_MAX_HEIGHT           264

#define PREVIEW_WIDGET_MIN_WIDTH            276
#define PREVIEW_WIDGET_MIN_HEIGHT           200


#define MAX_WINDOW_NUM_H 10
#define MAX_WINDOW_NUM_V 7

bool UKUITaskBtn::isDraggging = false;

UKUITaskBtn::UKUITaskBtn(UKUIWindow *window, UKUITaskBar *taskbar, QWidget *parent) :
    m_taskbar(taskbar)
{
    init();
    addWindowData(window);
}

UKUITaskBtn::UKUITaskBtn(QVector<UKUIWindow *> &windows, UKUITaskBar * taskbar, QWidget *parent) :
    m_taskbar(taskbar)
{
    init();

    foreach (UKUIWindow * window, windows) {
        addWindowData(window);
    }
}

UKUITaskBtn::~UKUITaskBtn()
{

}

void UKUITaskBtn::setAppName(const QString &appName)
{
    m_appName = appName;
}

QString UKUITaskBtn::appName() const
{
    return m_appName;
}

void UKUITaskBtn::addWindowData(UKUIWindow *window)
{
    Q_ASSERT(window);
    m_appName = window->getAppName();


    m_windows.append(window);
    m_mapWindowPreview[window] = createPreviewWidget(window);

    connect(window,&UKUIWindow::iconChanged, [this, window] {
        //updateText(wnd);
        updateIcon(window);
    });

    emit windowNumChanged();
}

void UKUITaskBtn::removeWindowData(UKUIWindow *window)
{
    m_windows.removeOne(window);

    m_mapWindowPreview[window]->deleteLater();
    m_mapWindowPreview.remove(window);

    emit windowNumChanged();
    //todo refresh preview and list view
}

QVector<UKUIWindow *> UKUITaskBtn::getWindows()
{
    return m_windows;
}

void UKUITaskBtn::init()
{
    m_mapWindowPreview.clear();
    m_windows.clear();

    m_listWidget = nullptr;
    mpScrollArea = nullptr;

    taskbuttonstatus=NORMAL;

    setCheckable(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    setMinimumWidth(1);
    setMinimumHeight(1);
    setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    setAcceptDrops(true);

    connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon()));
    connect(this, SIGNAL(windowNumChanged()), this, SLOT(changeTaskButtonStyle()));
    connect(this, &UKUITaskBtn::clicked,[this] {
        if(m_windows.size() == 1) {
            m_windows.first()->requestActivate();
        } else {
            showPreview();
        }
    });

}

UKUITaskbarPreviewWidget *UKUITaskBtn::createPreviewWidget(UKUIWindow *window)
{
    UKUITaskbarPreviewWidget* previewWidget = new UKUITaskbarPreviewWidget(window, m_taskbar);

    //todo connections
    return previewWidget;
}

void UKUITaskBtn::showPreview()
{
    //    int num = 0;
    //    if(m_taskbar->plugin()->panel()->isHorizontal()){
    //        num = MAX_WINDOW_NUM_H;
    //    } else {
    //        num = MAX_WINDOW_NUM_V;
    //    }
    //    if(m_windows.size() <= num) {
    //        showAllWindowByThumbnail();
    //    } else {
    showAllWindowByList();
    //    }
}

void UKUITaskBtn::hidePopUp()
{
    if(m_listWidget) {
        if(m_listWidget->isVisible()) {
            m_listWidget->hide(true);
        }
    }
}

void UKUITaskBtn::updateText(UKUIWindow *window)
{
    setText(window->getAppName());
}

void UKUITaskBtn::updateIcon(UKUIWindow *window)
{
    Q_ASSERT(window);
    QIcon ico;
    if(m_taskbar->isIconByClass()) {
        //todo
        //ico = QIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower());
    } else {
        ico = window->getIcon();
    }


    int mIconSize=m_taskbar->plugin()->panel()->iconSize();

    setIcon(ico);
    setIconSize(QSize(mIconSize,mIconSize));

    //UKUITaskBtn UKUITaskbarPreviewWidget should be same. when ukuitaskbtn update icon, preview widget should do the same.
    m_mapWindowPreview[window]->updateIcon();
}

void UKUITaskBtn::closeApplication()
{
    //todo
    qDebug()<<"TODO: this should close window !";
}

void UKUITaskBtn::changeTaskButtonStyle()
{
    if(m_windows.size() >1) {
        this->setStyle(new CustomStyle("taskbutton",true, this));
    } else {
        this->setStyle(new CustomStyle("taskbutton",false, this));
    }
}

void UKUITaskBtn::updateTaskList()
{
    if(m_listWidget) {
        m_listWidget->dataChanged();
    }
    updateTaskListPosition();
}

void UKUITaskBtn::updateTaskListPosition()
{
    if(m_listWidget) {
        int winWidth = 246;
        int winheight = 46;
        int iPreviewPosition = 0;
        int popWindowheight = (winheight + 3) * (m_windows.size() + 1);
        int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - m_taskbar->plugin()->panel()->panelSize();
        if(!m_taskbar->plugin()->panel()->isHorizontal())
        {
            screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect
        }
        m_listWidget->setFixedSize(winWidth,  popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight);

        if(m_taskbar->plugin()->panel()->isHorizontal())
        {
            iPreviewPosition =  m_taskbar->plugin()->panel()->panelSize()/2 - winWidth/2;
            m_listWidget->setGeometry( m_taskbar->plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(iPreviewPosition,0)), m_listWidget->size()));
        }
        else
        {
            iPreviewPosition =  m_taskbar->plugin()->panel()->panelSize()/2 - winWidth/2;
            m_listWidget->setGeometry( m_taskbar->plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,iPreviewPosition)), m_listWidget->size()));
        }
    }
}

void UKUITaskBtn::updatePreviewList()
{

}

void UKUITaskBtn::showAllWindowByList()
{
//    if(m_listWidget == nullptr) {
//        m_listWidget = new QWidget();
//    } else {
//        m_listWidget->show();
//        m_listWidget->raise();
//        return;
//    }

//    QVBoxLayout *listLayout = new QVBoxLayout();

//    foreach(UKUIWindow* window, m_mapWindowPreview.keys()) {
//        UKUITaskbarPreviewWidget* widget = m_mapWindowPreview[window];
//        widget->setPreviewVisible(false);
//        listLayout->addWidget(widget);
//    }

    //    m_listWidget->setLayout(listLayout);
    //    //m_listWidget->setWindowFlags(Qt::FramelessWindowHint);   //设置无边框窗口

    //    m_listWidget->show();
    if(m_listWidget == nullptr) {
        m_listWidget = new TaskList(this);
        connect(this, SIGNAL(windowNumChanged()), this, SLOT(updateTaskList()));
    } else {
        m_listWidget->show();
        m_listWidget->raise();
        return;
    }
    m_listWidget->setData(m_mapWindowPreview);
    updateTaskListPosition();
/*    int winWidth = 246;
    int winheight = 46;
    int iPreviewPosition = 0;
    int popWindowheight = (winheight + 3) * (m_windows.size() + 1);
    int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - m_taskbar->plugin()->panel()->panelSize();
    if(!m_taskbar->plugin()->panel()->isHorizontal())
    {
        screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect
    }
    m_listWidget->setFixedSize(winWidth,  popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight);

    if(m_taskbar->plugin()->panel()->isHorizontal())
    {
        iPreviewPosition =  m_taskbar->plugin()->panel()->panelSize()/2 - winWidth/2;
        m_listWidget->setGeometry( m_taskbar->plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(iPreviewPosition,0)), m_listWidget->size()));
    }
    else
    {
        iPreviewPosition =  m_taskbar->plugin()->panel()->panelSize()/2 - winWidth/2;
        m_listWidget->setGeometry( m_taskbar->plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,iPreviewPosition)), m_listWidget->size()));
    }*/
//    UKUIGroupPopup* mPopup = new UKUIGroupPopup(this);

//    int winWidth = 246;
//    int winheight = 46;
//    int iPreviewPosition = 0;
//    int popWindowheight = (winheight + 3) * (m_windows.size() + 1);
//    int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - m_taskbar->plugin()->panel()->panelSize();
//    if(!m_taskbar->plugin()->panel()->isHorizontal())
//    {
//        screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect
//    }
//    if(mPopup->layout()->count() > 0)
//    {
//        //removeSrollWidget();
//    }
//    mpScrollArea = new QScrollArea(this);
//    mpScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//    mpScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

//    mpScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//    mpScrollArea->setWidgetResizable(true);
//    mpScrollArea->setFrameStyle(QFrame::NoFrame);

//    mPopup->layout()->addWidget(mpScrollArea);
//    mPopup->setFixedSize(winWidth,  popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight);
//    mpScrollArea->setWidget(m_listWidget);

    m_listWidget->show();
    //mPopup->show();
    return;
  /*  if(m_listWidget == nullptr) {
        m_listWidget = new QWidget();
    } else {
        m_listWidget->show();
        m_listWidget->raise();
        return;
    }
    m_listWidget = new QWidget();

    mpScrollArea = new QScrollArea();
    mpScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    mpScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    mpScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    mpScrollArea->setWidgetResizable(true);
    mpScrollArea->setFrameStyle(QFrame::NoFrame);
    mpScrollArea->setWidget(m_listWidget);

    //QVBoxLayout *listLayout = new QVBoxLayout(m_listWidget);
    listLayout->setAlignment(Qt::AlignTop);
    listLayout->setSpacing(3);
    listLayout->setMargin(3);
    m_listWidget->setLayout(listLayout);


    int winWidth = 246;
    int winheight = 46;
    int iPreviewPosition = 0;
    int popWindowheight = (winheight + 3) * (m_windows.size() + 1);
    int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - m_taskbar->plugin()->panel()->panelSize();


    foreach(UKUIWindow* window, m_mapWindowPreview.keys()) {
        UKUITaskbarPreviewWidget* widget = m_mapWindowPreview[window];
        widget->setPreviewVisible(false);
        listLayout->addWidget(widget);
    }


    //       IUKUIPanelPlugin * plugin = m_taskbar->plugin();
    //       if(plugin->panel()->isHorizontal())
    //       {
    //           iPreviewPosition = plugin->panel()->panelSize()/2 - winWidth/2;
    //           qDebug()<<plugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(100,0)), QSize(200,100));
    //           m_listWidget->setGeometry(plugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(100,0)), QSize(200,100)));
    //       }
    //       else
    //       {
    //           iPreviewPosition = plugin->panel()->panelSize()/2 - winWidth/2;
    //           m_listWidget->setGeometry(plugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,iPreviewPosition)), QSize(200,100)));
    //       }
    m_listWidget->show();
    m_listWidget->raise();*/
}

void UKUITaskBtn::showAllWindowByThumbnail()
{

}

void UKUITaskBtn::dragEnterEvent(QDragEnterEvent *event)
{
    qDebug()<<"UKUITaskBtn::dragEnterEvent";
    event->acceptProposedAction();

    hidePopUp();

    if (event->mimeData()->hasFormat(mimeDataFormat()))
    {
        emit dragging(event->source(), event->pos());
        setAttribute(Qt::WA_UnderMouse, false);
    } else
    {
       // mDNDTimer->start();
    }

    return QToolButton::dragEnterEvent(event);
}

void UKUITaskBtn::dragMoveEvent(QDragMoveEvent *event)
{
    qDebug()<<"UKUITaskBtn::dragMoveEvent";
    if (event->mimeData()->hasFormat(mimeDataFormat()))
    {
        emit dragging(event->source(), event->pos());
        setAttribute(Qt::WA_UnderMouse, false);

    }
    QToolButton::dragMoveEvent(event);
}

void UKUITaskBtn::dragLeaveEvent(QDragLeaveEvent *event)
{
    qDebug()<<"UKUITaskBtn::dragLeaveEvent";
    QToolButton::dragLeaveEvent(event);
}

void UKUITaskBtn::dropEvent(QDropEvent *event)
{
    qDebug()<<"UKUITaskBtn::dropEvent";
    if (event->mimeData()->hasFormat(mimeDataFormat()))
    {
        emit dropped(event->source(), event->pos());
        setAttribute(Qt::WA_UnderMouse, false);
    }
    QToolButton::dropEvent(event);
}

void UKUITaskBtn::mousePressEvent(QMouseEvent *event)
{
    if (Qt::LeftButton == event->button())
        mDragStartPosition = event->pos();
    else if (Qt::MidButton == event->button() && m_taskbar->closeOnMiddleClick())
        closeApplication();

    QToolButton::mousePressEvent(event);
}

void UKUITaskBtn::mouseMoveEvent(QMouseEvent *event)
{
    if (!(event->buttons() & Qt::LeftButton))
        return;

    if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
        return;

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData());
    QIcon ico = icon();
    QPixmap img = ico.pixmap(ico.actualSize({32, 32}));
    drag->setPixmap(img);
    switch (m_taskbar->panel()->position())
    {
        case IUKUIPanel::PositionLeft:
        case IUKUIPanel::PositionTop:
            drag->setHotSpot({0, 0});
            break;
        case IUKUIPanel::PositionRight:
        case IUKUIPanel::PositionBottom:
            drag->setHotSpot(img.rect().bottomRight());
            break;
    }

    isDraggging = true;
    drag->exec();

    // if button is dropped out of panel (e.g. on desktop)
    // it is not deleted automatically by Qt
    drag->deleteLater();
    isDraggging = false;

    QAbstractButton::mouseMoveEvent(event);
}

QMimeData *UKUITaskBtn::mimeData()
{
    QMimeData *mimedata = new QMimeData;
    QByteArray ba;
    QDataStream stream(&ba,QIODevice::WriteOnly);
    //stream << (qlonglong)(appName());
    stream <<appName();

    mimedata->setData(mimeDataFormat(), ba);
    return mimedata;
}

void UKUITaskBtn::showEvent(QShowEvent *event)
{
    emit visibilityChanged(true);
    return QToolButton::showEvent(event);
}

void UKUITaskBtn::hideEvent(QHideEvent *event)
{
    emit visibilityChanged(false);
    return QToolButton::hideEvent(event);
}

void UKUITaskBtn::enterEvent(QEvent *event)
{
    //show preview
    qDebug()<<"enterEvent ..................";
    showPreview();

}

void UKUITaskBtn::leaveEvent(QEvent *event)
{
    QTimer::singleShot(CommonUtil::getPopWindowDelayTime(), this, [=](){
        if(m_listWidget) {
            m_listWidget->hide();
        }
    });
}

void UKUITaskBtn::contextMenuEvent(QContextMenuEvent *event)
{

}

void UKUITaskBtn::updateIcon()
{
    foreach (UKUIWindow * wnd, m_windows) {
        updateIcon(wnd);
    }
}


